package anveshitha.query;

import static anveshitha.config.AnveshithaConstants.FILE_SEPARATOR;
import static anveshitha.config.AnveshithaConstants.JAVA;
import static anveshitha.config.AnveshithaConstants.LUCENE_INDEX_DIR;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.PerFieldAnalyzerWrapper;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

import anveshitha.analyzers.JavaSourceCodeAnalyzer;
import anveshitha.analyzers.KeywordAnalyzer;
import anveshitha.config.AnveshithaConstants;
import anveshitha.config.AnveshithaConstants.FieldEnum;


public class QueryExecutor {
	
	private static Logger log = Logger.getLogger(QueryExecutor.class);
	
	File fIndexDir;
	String fileExtn;
	Analyzer codeAnalyzer;
	
	public QueryExecutor(String fileExtn,Analyzer codeAnalyzer) {
		super();
		this.fileExtn = fileExtn;
		this.fIndexDir = new File(LUCENE_INDEX_DIR + fileExtn + FILE_SEPARATOR);
		this.codeAnalyzer = codeAnalyzer;
	}


	public List<QueryResult> execute(String sQuery,boolean allowLeadingWildcard) throws IOException, ParseException{
		
		PerFieldAnalyzerWrapper analyzer = new PerFieldAnalyzerWrapper(codeAnalyzer);		
		analyzer.addAnalyzer(FieldEnum.IMPORT.name(), new KeywordAnalyzer());
		
		Directory fsDir;
		fsDir = FSDirectory.getDirectory(fIndexDir);
		IndexSearcher indexSearcher = new IndexSearcher(fsDir);
		QueryParser queryParser = new QueryParser(FieldEnum.CLASSNAME.name(),analyzer);
		queryParser.setAllowLeadingWildcard(allowLeadingWildcard);
		Query query = queryParser.parse(sQuery);
		
		long start = System.currentTimeMillis();
		log.info("Searching...");
		Hits hits = indexSearcher.search(query);
		long end = System.currentTimeMillis();

		log.info("Found " + hits.length() + " docs in "
				+ (end - start) + " millisec");

//		for (int i = 0; i < hits.length(); i++) {
//			Document doc = hits.doc(i);
//			System.out.println(Arrays.toString(doc.getValues(FieldEnum.METHODNAME.name())) + " with a score of "
//					+ hits.score(i));
//		}
		
		List<QueryResult> alResults = processHits(hits);

		indexSearcher.close();
		
		return alResults;
		
	}
	
	private List<QueryResult> processHits(Hits hits) throws CorruptIndexException, IOException{
		
		List<QueryResult> alResults = new ArrayList<QueryResult>();
		QueryResult result;
		
		for (int i = 0; i < hits.length(); i++) {
			Document doc = hits.doc(i);
			result = new QueryResult();
			
			//load into the result
			result.setClassName(doc.get(FieldEnum.CLASSNAME.name()));
			result.setComments(doc.get(FieldEnum.COMMENTS.name()));
			result.setFilepath(doc.get(FieldEnum.FILEPATH.name()));
			result.setImports(doc.getValues(FieldEnum.IMPORT.name()));
			result.setInterfaces(doc.getValues(FieldEnum.IMPLEMENTS.name()));
			result.setMethods(doc.getValues(FieldEnum.METHODNAME.name()));
			result.setPackageName(doc.get(FieldEnum.PACKAGENAME.name()));
			result.setSuperClassName(doc.get(FieldEnum.EXTENDS.name()));
			
			//add to list
			alResults.add(result);
			
		}
		
		return alResults;
	}
	
	/** Main for running test case by itself. */
	public static void main(String args[]) {
		try {

			AnveshithaConstants.loadConfigData("");
			String q = "METHODCODE: java";
			QueryExecutor exe = new QueryExecutor(JAVA,new JavaSourceCodeAnalyzer());
			exe.execute(q,true);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
